package com.inspectortime.service.search.impl;

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.springframework.util.StringUtils;

import com.inspectortime.domain.InspectorCompany;
import com.inspectortime.service.search.InspectorSearchDao;
import com.inspectortime.service.search.InspectorSearchService;

/**
 * Default implementation of InspectorSearchService
 * 
 * @author bones
 *
 */
public class InspectorSearchServiceImpl implements InspectorSearchService {
	
	private InspectorSearchDao inspectorSearchDao;

	/**
	 * Performs a series of individual searches based on the searchTerm to come up with a list of relevant results
	 */
	public Set<InspectorCompany> searchForInspectorCompany(String searchTerm) {
		
		Set<InspectorCompany> searchResults = null;
		
		searchTerm = StringUtils.trimWhitespace(searchTerm);
		
		//First look for exact company name matches
		List<InspectorCompany> companies = inspectorSearchDao.searchInspectorCompanyByName(searchTerm);
		if (companies.size() == 1) {
			//Exact company match?
			if (companies.get(0).getName().equalsIgnoreCase(searchTerm)) {
				searchResults = new LinkedHashSet<InspectorCompany>(companies);
				return searchResults;
			}
		}

		if (!searchTerm.contains(" ") && !searchTerm.contains(",")) {
			return searchBySingleTerm(searchTerm);
		}
		
		if (searchTerm.contains(",")) {
			
			String terms[] = searchTerm.split(",");
			
			//is it two words, seperated by a comma?  If so, assume last, first
			if (terms.length == 2) {
				return searchByTwoTerms(terms[1], terms[0], searchTerm);
			}
		}
		
		//two words seperated by a space
		String terms[]  = searchTerm.split(" ");
		if (terms.length == 2) {
			return searchByTwoTerms(terms[0], terms[1], searchTerm);
		} 
		

		//Try searching by different pairs of search terms
		List<String> termlist = Arrays.asList(terms);
		for (int i = 0; i < termlist.size(); i++) {
			int secondTermIndex = i + 1;
			if (secondTermIndex >= termlist.size()) {
				secondTermIndex = 0;
			}
				
			String firstTerm = termlist.get(i);
			String secondTerm = termlist.get(secondTermIndex);
			
			searchResults = new LinkedHashSet<InspectorCompany>();
			searchResults.addAll(searchByTwoTerms(firstTerm, secondTerm, firstTerm + " " + secondTerm));
		}
		
		return searchResults;
	}
	
	protected Set<InspectorCompany> searchBySingleTerm(String searchTerm) {
		Set<InspectorCompany> searchResults = new LinkedHashSet<InspectorCompany>();
		
		//First look for company name matches
		searchResults.addAll(inspectorSearchDao.searchInspectorCompanyByName(searchTerm));
		//Then look for inspector/realtor last names
		searchResults.addAll(searchByLastName(searchTerm));
		
		//If no searches were successful, try searching by first name
		if (searchResults.size() == 0) {
			searchResults.addAll(searchByFirstName(searchTerm));
		}
		return searchResults;
	}
	
	protected Set<InspectorCompany> searchByTwoTerms(String first, String last, String originalTerm) {
		
		Set<InspectorCompany> searchResults = new LinkedHashSet<InspectorCompany>();
		
		if (StringUtils.hasText(first)) {
			first = first.trim();
		}
		if (StringUtils.hasText(last)) {
			last = last.trim();
		}
		
		//try an exact match on company name
		searchResults.addAll(inspectorSearchDao.searchInspectorCompanyByName(originalTerm));
		searchResults.addAll(searchByFirstLastName(first, last));
		
		if (searchResults.isEmpty()) {
			//try searching for each individual term
			searchResults.addAll(searchBySingleTerm(first));
			searchResults.addAll(searchBySingleTerm(last));
		}
		
		return searchResults;
	}
	
	/**
	 * Look for inspectors or realtors with a similar first and last name
	 */
	protected Set<InspectorCompany> searchByFirstLastName(String first, String last) {
		
		Set<InspectorCompany> searchResults = new LinkedHashSet<InspectorCompany>();
		
		//inspector name
		searchResults.addAll(inspectorSearchDao.searchInspectorCompanyByInspectorName(first, last));
		if (searchResults.size() == 1) {
			return searchResults;
		}
		
		//realtor name
		searchResults.addAll(inspectorSearchDao.searchInspectorCompanyByRealtorName(first, last));
		
		return searchResults;
	}
	
	/**
	 * Look for inspectors or realtors with a similar last name
	 */
	protected Set<InspectorCompany> searchByLastName(String name) {
		
		Set<InspectorCompany> searchResults = new LinkedHashSet<InspectorCompany>();
		
		//inspector name
		searchResults.addAll(inspectorSearchDao.searchInspectorCompanyByInspectorName(null, name));
		
		//realtor name
		searchResults.addAll(inspectorSearchDao.searchInspectorCompanyByRealtorName(null, name));
		
		return searchResults;
	}
	
	/**
	 * Look for inspectors or realtors with a similar first name
	 */
	protected Set<InspectorCompany> searchByFirstName(String first) {
		
		Set<InspectorCompany> searchResults = new LinkedHashSet<InspectorCompany>();
		
		//inspector name
		searchResults.addAll(inspectorSearchDao.searchInspectorCompanyByInspectorName(first, null));

		//realtor name
		searchResults.addAll(inspectorSearchDao.searchInspectorCompanyByRealtorName(first, null));
		
		return searchResults;
	}
	
	
	
	public InspectorSearchDao getInspectorSearchDao() {
		return inspectorSearchDao;
	}

	public void setInspectorSearchDao(InspectorSearchDao inspectorSearchDao) {
		this.inspectorSearchDao = inspectorSearchDao;
	}


}
